
class Animal {
    public String name;
    public int age;
    //构造方法
    public Animal(String name,int age) {
        this.name = name;
        this.age = age;
    }
    //变量方法
     public void eat() {//父类被static、private修饰的方法、构造方法都不能被重写
        System.out.println(this.name + "正在吃....");
    }
}

class Bird extends Animal {
    public Bird(String name,int age) {
        super(name,age);
    }
    public void fly() {
        System.out.println(this.name + "正在飞....");
    }

    @Override//注释 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心
    //将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法
    //构成重写
    public void eat() {//重写
        System.out.println(this.name + "正在吃小虫子....");
        //访问权限不能比父类中被重写的方法的访问权限更低。
        // 例如：如果父类方法被public修饰，则子类中重写该方法就不能声明为 protected
    }
}
class Dog extends Animal {
    public String color;

    public Dog(String name,int age,String color) {
        super(name,age);
        this.color = color;
    }
    @Override//注释
    public void eat() {//重写
        System.out.println(this.name + "正在吃狗粮.....");
    }
    public void barks() {
        System.out.println(this.name + "汪汪叫....");
    }
}
public class Test {
    public static void main4(String[] args) {
        Animal animal2 = new Dog("小黑",1,"黑色");
       if(animal2 instanceof Bird)//为了避免不安全问题 每次使用instanceof判断
       {
           Bird bird2 = (Bird)animal2;
           bird2.fly();//ClassCastException 不安全性：如果向下类型中不包含该向下的方法将无法转化
       }else {
           System.out.println("error");
       }

        Animal animal1 = new Bird("布谷鸟",1);
        Bird bird1 = (Bird)animal1;
        bird1.fly();
        //animal.fly();//无法直接调用 进行向下转型
    }
    public static void main3(String[] args) {
        Dog dog = new Dog("小黑",1,"黑色");
        dog.eat();
        Bird bird = new Bird("布谷鸟",1);
        bird.eat();
        //重写
        //【重写的设计原则】
        //对于已经投入使用的类，尽量不要进行修改。最好的方式是：重新定义一个新的类，来重复利用其中共性的内容，
        //并且添加或者改动新的内容
        //动态绑定:编译时不确定调用谁 运行时才确定调用谁
        //静态绑定:编译时就确定调用谁
    }

    //传返回值
//    public  static Animal func() {
//        //return new Dog("小黑",1,"黄色");//返回值
//        return new Bird("布谷",1);
//    }
    //传参
//    public static void fun(Animal animal) {
//        animal.eat();
//    }
    public static void main2(String[] args) {
        //多态
        //1. 必须在继承体系下
        //2. 子类必须要对父类中方法进行重写
        //3. 通过父类的引用调用重写的方法
        //多态体现：在代码运行时，当传递不同类对象时，会调用对应类中的方法。
        //向上转型：实际就是创建一个子类对象，将其当成父类对象来使用。
        //语法：父类类型 类名 = new 子类类型
        //1.直接赋值(向上转型)
//        Animal animal = new Dog("旺财",1,"黄色");//父类使用子类初始化
//        animal.eat();
//        Animal animal1 = new Bird("布谷鸟",2);
//        animal1.eat();
        //animal.barks();//向上转型时 无法调用子类方法
        // 2.传参
//        Dog dog = new Dog("旺财",1,"黄色");
//        fun(dog);
//        Bird bird = new Bird("布谷鸟",2);
//        fun(bird);
        //3.返回值
//        func().eat();
//        func().eat();
        //向上转型的优点：让代码实现更简单灵活。
        //向上转型的缺陷：不能调用到子类特有的方法。

        //向下转型

    }
//    public static void main1(String[] args) {
//        Dog dog = new Dog("小灰",1,"灰色");
//        dog.eat();
//        dog.barks();
//    }
}
